package org.jflame.web.spring.controller;

import org.jflame.commons.file.MimeTypes;
import org.jflame.commons.model.CallResult;
import org.jflame.commons.util.ArrayHelper;
import org.jflame.commons.util.StringHelper;
import org.jflame.context.filemanager.SignedUrl;
import org.jflame.web.WebFileProperties;
import org.jflame.web.WebFileProperties.DownloadProp;
import org.jflame.web.WebFileProperties.UploadProp;
import org.jflame.web.spring.SpringFileService;

import java.io.IOException;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletResponse;

@Controller
@RequestMapping("${jflame.web.server-path:/file}")
public class FileController {

    protected final Logger logger = LoggerFactory.getLogger(FileController.class);

    @Autowired
    protected SpringFileService fileService;
    @Autowired(required = false)
    protected WebFileProperties defaultCfg;
    // @Autowired(required = false)
    // protected DownloadProp defaultDownloadCfg;

    @PostConstruct
    public void init() {
        if (defaultCfg == null) {
            defaultCfg = new WebFileProperties();
        }
        if (defaultCfg.getDownload()
                .getAllowTypes() == null) {
            defaultCfg.getDownload()
                    .setAllowTypes(ArrayHelper.unionAll(MimeTypes.WEB_IMAGE_EXTENSIONS, MimeTypes.DOC_EXTENSIONS));
        }

        if (defaultCfg.getUpload()
                .getAllowTypes() == null) {
            defaultCfg.getUpload()
                    .setAllowTypes(ArrayHelper.unionAll(MimeTypes.WEB_IMAGE_EXTENSIONS, MimeTypes.DOC_EXTENSIONS));
        }
    }

    /**
     * 下载文件
     * 
     * @param downFile 要下载的文件相对路径
     * @param response
     * @throws IOException
     */
    @GetMapping("/download/{downFile}")
    public void download(@PathVariable String downFile, HttpServletResponse response) throws IOException {
        fileService.download(downFile, defaultCfg.getDownload(), response);
    }

    /**
     * 预览文件,保持文件content-type
     * 
     * @param previewFile 要下载的文件相对路径
     * @param response
     * @throws IOException
     */
    @GetMapping("/preview/{previewFile}")
    public void preview(@PathVariable String previewFile, HttpServletResponse response) throws IOException {
        DownloadProp prop = new DownloadProp();
        prop.setKeepContentType(true);
        prop.setAllowTypes(defaultCfg.getDownload()
                .getAllowTypes());
        prop.setDir(defaultCfg.getDownload()
                .getDir());
        fileService.download(previewFile, prop, response);
    }

    @PostMapping("/upload")
    @ResponseBody
    public CallResult<String> uploadFile(MultipartFile uploadFile) {
        return fileService.uploadFile(uploadFile, defaultCfg.getUpload());
    }

    /**
     * 生成前端POST方式直传OSS文件的上传参数
     *
     * @param fileName 要上传的文件名或扩展名(带.)
     * @param dir 文件保存目录,相对目录,可以空
     * @return
     */
    @GetMapping("/post-upload-params")
    @ResponseBody
    public CallResult<Map<String,String>> generatePostUploadParams(@RequestParam String fileName, String dir) {
        UploadProp prop;
        if (StringHelper.isNotEmpty(dir)) {
            prop = new UploadProp();
            prop.setDir(dir);
            prop.setAllowTypes(defaultCfg.getUpload()
                    .getAllowTypes());
            prop.setPresginExpireTime(defaultCfg.getUpload()
                    .getPresginExpireTime());
            prop.setMaxFileSize(defaultCfg.getUpload()
                    .getMaxFileSize());
        } else {
            prop = defaultCfg.getUpload();
        }
        return fileService.generatePostObjectParams(fileName, prop);
    }

    /**
     * 生成前端PUT方式直传OSS文件的上传预签名url参数
     *
     * @param fileName 要上传的文件名或扩展名(带.)
     * @param dir 文件保存目录,相对目录,可以空
     * @return
     */
    @GetMapping("/put-presigned-url")
    @ResponseBody
    public CallResult<SignedUrl> generatePutUploadSignedUrl(@RequestParam String fileName, String dir) {
        UploadProp prop;
        if (StringHelper.isNotEmpty(dir)) {
            prop = new UploadProp();
            prop.setDir(dir);
            prop.setAllowTypes(defaultCfg.getUpload()
                    .getAllowTypes());
            prop.setPresginExpireTime(defaultCfg.getUpload()
                    .getPresginExpireTime());
            prop.setMaxFileSize(defaultCfg.getUpload()
                    .getMaxFileSize());
        } else {
            prop = defaultCfg.getUpload();
        }
        return fileService.generatePresignPutUrl(fileName, prop);
    }
}
